#include "global.h"


static int rdir = 0;

int rndnum(int max)
{
	return rand() % (max+1);
}

static int r_fails[4] = {0};
static int r_successes[4] = {0};

static int map_w, map_h;

int rndval(int a, int b)
{
	int temp;
	
	if (a == b) {
		return a;
	}
	
	if (b < a) {
		temp = a;
		a = b;
		b = temp;
	}
	
	temp = rndnum(b - a);
	
	return temp + a;
}

static void CreateRoomDimensions(int *w, int *h)
{
	*w = rndval(5, 12);
	*h = rndval(5, 12);
	
	if (*w == 12) {
		*w = rndval(12, 15);
	}
	if (*h == 12) {
		*h = rndval(12, 15);
	}
}

static int NoRoomCollision(int place_x, int place_y, int room_w, int room_h)
{
	int x, y;
	
	if (place_x < 0) return 0;
	if (place_y < 0) return 0;
	if ((place_x+room_w) > map_w) return 0;
	if ((place_y+room_h) > map_h) return 0;

	for (y = 0; y < room_h; y++) {
		for (x = 0; x < room_w; x++) {
			if (mapgen_get_tile(place_x + x, place_y + y) != 17) return 0;
		}
	}
	
	return 1;
}

static void NewRoom(int place_x, int place_y, int room_w, int room_h, int creator)
{
	int i;

	igraph_add_vertices(&dungeon_graph, 1, NULL);

	set_roominfo(&dungeon_graph, total_rooms, &rooms[total_rooms]);

	// Draw this room
	mapgen_draw_room(place_x, place_y, room_w, room_h, total_rooms);
	
	rooms[total_rooms].x = place_x;
	rooms[total_rooms].y = place_y;
	rooms[total_rooms].w = room_w;
	rooms[total_rooms].h = room_h;
	rooms[total_rooms].room_type = 0;
	rooms[total_rooms].room_param = 0;
	
	rooms[total_rooms].creator = creator;
	
	total_rooms++;

	if (creator == -1) return;
	
	int sr_cps = 0;
	int sr_cp[100];
	
	int sr_nps = 0;
	int sr_np[100];

	struct cplist_t cplist[100];
	int connect_points = find_connection_points(total_rooms - 1, cplist);

	for (i = 0; i < connect_points; i++) {
		if (cplist[i].r == creator) {
			sr_cp[sr_cps++] = i;
		} else {
			sr_np[sr_nps++] = i;
		}
	}
	
	//printf("cps: %d      room: %d\n", sr_cps, total_rooms);

	i = rndval(0, sr_cps-1);
	MakeConnect(cplist[sr_cp[i]].x, cplist[sr_cp[i]].y, cplist[sr_cp[i]].t);

//	printf("Created room %d, connecting %d and %d\n", total_rooms - 1, total_rooms - 1, cplist_r[sr_cp[i]]);
	igraph_add_edge(&dungeon_graph, total_rooms - 1, cplist[sr_cp[i]].r);
	add_edge_weight(total_rooms-1,cplist[sr_cp[i]].r);
	
	// one other connection (if we can)
	if (sr_nps > 0) {
		i = rndval(0, sr_nps-1);
		MakeConnect(cplist[sr_np[i]].x, cplist[sr_np[i]].y, cplist[sr_np[i]].t);

		igraph_add_edge(&dungeon_graph, total_rooms - 1, cplist[sr_np[i]].r);
		add_edge_weight(total_rooms-1,cplist[sr_np[i]].r);
	}

}

static int AddChild(int room_id)
{
	roominfo r = rooms[room_id];
	int place_x = r.x;
	int place_y = r.y;
	int room_w = r.w;
	int room_h = r.h;
	int new_w, new_h, new_x, new_y;
	int room_pos;
	
	int trying;
	int attempts;
	

	
	trying = 1;
	attempts = 0;
	while (trying) {
		attempts++;
		
		if (( (total_rooms+1) % 500)==0) {
			new_w = 20;
			new_h = 15;
		} else {
			CreateRoomDimensions(&new_w, &new_h);
		}
		
		room_pos = (rdir++)%4;
		
		if (room_pos < 2) {
			// vertical placement
			new_x = rndval(place_x - (new_w - 3), place_x + (room_w - 3));
			if (room_pos == 0) {
				new_y = place_y - new_h;
			} else {
				new_y = place_y + room_h;
			}
		} else {
			// horiz placement
			new_y = rndval(place_y - (new_h - 3), place_y + (room_h - 3));
			if (room_pos == 2) {
				new_x = place_x - new_w;
			} else {
				new_x = place_x + room_w;
			}
		}
		
		if (NoRoomCollision(new_x, new_y, new_w, new_h)) {
			//printf("SUCCESS\n");
			r_successes[room_pos]++;
			NewRoom(new_x, new_y, new_w, new_h, room_id);
			return 1;
		} else {
			//printf("FAIL %d\n", attempts);
			r_fails[room_pos]++;
			if (attempts > 20) return 0;
		}
	}
	return 0;
}

int generate_dungeon_meritous(int w, int h)
{
	int attempts = 0;
	int rx = rndval(5, 20);
	int ry = rndval(4, 15);
	rdir = rand()%4;
	
	map_w = w;
	map_h = h;

	NewRoom(w / 2 - rx / 2, h / 2 - ry / 2, rx, ry, -1);
	
	for (attempts = 0; attempts < 100000; attempts++) {
		AddChild(rndval(rndval(0, total_rooms-1), total_rooms-1));
		if (total_rooms == 3000) break;
	}
	
	return 1;
}

//Hack for fast integration into freedroidRPG
#if 0
int turn_into_level(level *target)
{
	int y, x;
	
	for (y = 0; y < map.h; y++) {
		for (x = 0; x < map.w; x++) {
			switch (mapgen_get_tile(x,y)) {
				case 4:
					action_create_obstacle(target, x + 0.5, y + 1, 2);
					action_set_floor(target, x, y, 0);
					break;
				case 5:
					action_create_obstacle(target, x + 0.5, y, 2);
					action_set_floor(target, x, y, 0);
					break;
				case 6:
					action_create_obstacle(target, x + 1.0, y + 0.5, 1);
					action_set_floor(target, x, y, 0);
					break;
				case 7:
					action_create_obstacle(target, x, y + 0.5, 1);
					action_set_floor(target, x, y, 0);
					break;
				case 11:
					action_create_obstacle(target, x + 0.5, y, 2);
					action_create_obstacle(target, x, y + 0.5, 1);
					action_set_floor(target, x, y, 0);
					break;
				case 10:
					action_create_obstacle(target, x + 0.5, y, 2);
					action_create_obstacle(target, x + 1, y + 0.5, 1);
					action_set_floor(target, x, y, 0);
					break;
				case 9:
					action_create_obstacle(target, x, y + 0.5, 1);
					action_create_obstacle(target, x + 0.5, y + 1, 2);
					action_set_floor(target, x, y, 0);
					break;
				case 8:
					action_create_obstacle(target, x + 1, y + 0.5, 1);
					action_set_floor(target, x, y, 0);
					action_create_obstacle(target, x + 0.5, y + 1, 2);
					break;

				case 12:
					action_set_floor(target, x, y, 0);
					break;

				case 17:
					action_set_floor(target, x, y, 31);
					break;

				case 16:
					action_set_floor(target, x, y, 56);
				    break;	

				case 15:
					action_create_obstacle(target, x + 1, y + 0.5, 11);
					action_set_floor(target, x, y, 58);
				    break;	
				
				case 14:
					action_create_obstacle(target, x + 0.5, y, 6);
					action_set_floor(target, x, y, 57);
				    break;	

				case 13:
					action_set_floor(target, x, y, 59);
				    break;	

				default:
					action_set_floor(target, x, y, mapgen_get_tile(x,y));
			}
		}
	}

	return 0;
}
#endif
